package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.WmUserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private AutoScanService autoScanService;

    @Override
    public ResponseResult findList(WmNewsPageReqDto dto) {

        if(dto == null){
            return new PageResponseResult(0,0,0);
        }
        Short status = dto.getStatus();
        Date beginPubDate = dto.getBeginPubDate();
        Integer channelId = dto.getChannelId();
        Date endPubDate = dto.getEndPubDate();
        String keyword = dto.getKeyword();

        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(status != null,WmNews::getStatus,status);
        wrapper.between(beginPubDate != null && endPubDate != null,WmNews::getPublishTime,beginPubDate,endPubDate);
        wrapper.eq(channelId != null,WmNews::getChannelId,channelId);
        wrapper.like(StringUtils.isNotEmpty(keyword),WmNews::getTitle,keyword);
        wrapper.eq(WmNews::getUserId, WmUserThreadLocal.get().getId());
        wrapper.orderByDesc(WmNews::getPublishTime);

        Integer page = dto.getPage();
        Integer size = dto.getSize();

        Page<WmNews> newsPage = new Page<>(page,size);
        Page<WmNews> wmNewsPage = wmNewsMapper.selectPage(newsPage, wrapper);
        Long total = wmNewsPage.getTotal();
        PageResponseResult pageResponseResult = new PageResponseResult(page, size, total.intValue());
        pageResponseResult.setData(wmNewsPage.getRecords());
        return pageResponseResult;
    }

    @Autowired
    private IScheduleClient iScheduleClient;

    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //1.提取新闻内容
        WmNews news = getNews(dto);
        //2.插入新闻表
        int newResult = wmNewsMapper.insert(news);
        if(newResult < 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //3.判断是否是草稿
        Short status = dto.getStatus();
        if(status == 0){
            log.info("文章为草稿，所以没有添加素材");
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //4.提取内容图
        List<String> contentImages = getContentImages(dto.getContent());

        //5.提取封面图
        List<String> coverImages = new ArrayList<>();

        //自动布局
        if (dto.getType() == -1) {
            List<String> list = autoLayout(contentImages);
            // 更新一下news表，布局方式改掉
            Integer coverImageSize = list.size();
            news.setType(coverImageSize.shortValue());
            wmNewsMapper.updateById(news);
        } else {
            coverImages = dto.getImages();
        }
        // 6. 插入内容图
        addMaterial(contentImages, 1, news.getId());

        // 7. 插入封面图
        addMaterial(coverImages, 0, news.getId());

       /* //8.提交审核
        try {
            autoScanService.autoScanWmNews(news.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        Boolean addTaskResult = addToTask(news.getId(), news.getPublishTime().getTime());
        if(!addTaskResult){
            throw new RuntimeException("任务添加失败");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        if(wmNewsDto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer dtoId = wmNewsDto.getId();
        WmNews wmNews = wmNewsMapper.selectById(dtoId);
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }
        Short status = wmNews.getStatus();
        if(status != 9){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE,"当前文章不是发布状态,不能上下架");
        }

        wmNews.setEnable(wmNewsDto.getEnable());
        int updateResult = wmNewsMapper.updateById(wmNews);
        if(updateResult < 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"修改文章失败");
        }
        kafkaTemplate.send("news.down.up.topic", JSON.toJSONString(wmNews));

        return ResponseResult.okResult("");
    }

    private Boolean addToTask(Integer newsId,Long executeTime){
        Task task = new Task();
        task.setExecuteTime(executeTime);

        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);
        task.setParameters(ProtostuffUtil.serialize(wmNews));

        ResponseResult responseResult = iScheduleClient.addTask(task);
        if(responseResult != null && responseResult.getCode() == 200){
            return true;
        }

        return false;
    }

    public WmNews getNews(WmNewsDto dto){
        if(dto == null){
            log.warn("dto不能为空");
            return null;
        }

        WmNews wmNews = new WmNews();
        //dto和wmnews相同字段进行赋值
        BeanUtils.copyProperties(dto,wmNews);
        if(dto.getType() == -1){
            wmNews.setType(null);
        }
        List<String> images = dto.getImages();
        String imagesString = StringUtils.join(images, ",");
        wmNews.setImages(imagesString);
        wmNews.setCreatedTime(new Date());
        wmNews.setUserId(WmUserThreadLocal.get().getId());
        // 3. 返回wmNews
        return wmNews;

    }

    public List<String> getContentImages(String content){
        if(StringUtils.isEmpty(content)){
            return new ArrayList<>();
        }
        List<Map> maps = JSON.parseArray(content, Map.class);
        if(CollectionUtils.isEmpty(maps)){
            return new ArrayList<>();
        }

        List<String> imageList = new ArrayList<>();
        for (Map map : maps) {
            if(CollectionUtils.isEmpty(map)){
                continue;
            }
            Object type = map.get("type");
            if ("image".equals(type)) {
                try {
                    String value = (String) map.get("value");
                    imageList.add(value);
                } catch (Exception e) {
                    log.warn("value解析失败");
                    continue;
                }
            }
        }
        return imageList;
    }

    public List<String> autoLayout(List<String> contentImages) {
        // 从内容图获取图片，填充到封面图上
        int size = contentImages.size();
        List<String> coverImages = new ArrayList<>();

        // 判断内容图的长度
        // 长度为 0 -> 无图
        if (size == 0) {
            return coverImages;
        }
        // 长度为 1 -> 单图
        else if (size == 1) {
            coverImages.add(contentImages.get(0));
            return coverImages;
        }
        // 长度大于3 -> 多图
        else if (size > 3) {
            coverImages.addAll(contentImages.subList(0, 2));
            return coverImages;
        }

        return contentImages;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(List<String> images, Integer type, Integer newsId) {
        if (CollectionUtils.isEmpty(images)) {
            log.warn("素材不能为空");
            return false;
        }

        // 1. 遍历图片集合
        for (String image : images) {
            if (StringUtils.isEmpty(image)) {
                continue;
            }

            // 2. 判断当前图片是否存在于素材表中
            LambdaQueryWrapper<WmMaterial> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WmMaterial::getUrl, image);
            WmMaterial wmMaterial = wmMaterialMapper.selectOne(wrapper);

            Integer materialId = null;
            if (wmMaterial == null) {
                WmMaterial material = new WmMaterial();
                material.setUserId(WmUserThreadLocal.get().getId());
                material.setUrl(image);
                material.setIsCollection((short) 0);
                material.setType((short) 0);
                material.setCreatedTime(new Date());

                int materialResult = wmMaterialMapper.insert(material);
                if (materialResult < 1) {
                    log.warn("素材插入失败");
                    throw new RuntimeException("素材插入失败");
                }

                // 2.2 如不存在，插入素材，返回id
                materialId = material.getId();
            } else {
                // 2.1 如果已存在，返回id
                materialId = wmMaterial.getId();
            }

            // 3. 插入关系表
            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setMaterialId(materialId);
            newsMaterial.setNewsId(newsId);
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 0);

            int newMaterialResult = wmNewsMaterialMapper.insert(newsMaterial);
            if (newMaterialResult < 1) {
                throw new RuntimeException("素材关系插入失败");
            }
        }

        // 4. 返回true
        return true;
    }
}
